package la.iok.aone.monitor.youtube.model;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import la.iok.aone.monitor.youtube.util.excel.annotation.ExcelField;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.concurrent.ScheduledExecutorTask;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

@Data
@ApiModel(value = "YoutubeLink", description = "Youtube链接信息")
//@JsonIgnoreProperties(value={"checked", "checkTime", "errorMsg", "monitorCount", "monitorTime", "delFlag", "createTime", "updateTime", "remark"})
public class YoutubeLink implements Serializable {

    // 交给多画面监控使用的View格式
    public interface MonitorView {}

    @JsonView(MonitorView.class)
    @ApiModelProperty(value = "链接编号", position = 0)
    private int id;
    @JsonView(MonitorView.class)
    @ApiModelProperty(value = "视频标题", position = 1)
    @ExcelField(title="Title", align=2, sort=10)
    private String title;
    @JsonView(MonitorView.class)
    @ApiModelProperty(value = "视频分类", position = 2)
    @ExcelField(title="Categorys", align=2, sort=20)
    private String category;
    @JsonView(MonitorView.class)
    @ApiModelProperty(value = "链接地址", position = 3)
    @ExcelField(title="Source", align=2, sort=30)
    private String link;
    @JsonView(MonitorView.class)
    @ApiModelProperty(value = "视频编号", position = 4)
    private String videoId;
    /**
     * 龙视平台链接编号，调用龙视下线链接接口时需要用到
     */
    @ApiModelProperty(hidden = true)
    private String feedbackId;
    @ApiModelProperty(hidden = true)
    private boolean checked;
    /**
     * 检测错误次数，默认情况下连续三次检测获取不到节目信息则调用龙视反馈接口下线链接。
     */
    @ApiModelProperty(hidden = true)
    private int checkErrorTimes;
    @ApiModelProperty(hidden = true)
    private Date checkTime;
    @ApiModelProperty(hidden = true)
    private String errorMsg;
    @ApiModelProperty(hidden = true)
    private int monitorCount;
    @ApiModelProperty(hidden = true)
    private Date monitorTime;
    @ApiModelProperty(hidden = true)
    private boolean delFlag;
    @ApiModelProperty(hidden = true)
    private Date createTime;
    @ApiModelProperty(hidden = true)
    private Date updateTime;
    @ApiModelProperty(hidden = true)
    private String remark;

    /**
     * 使用默认参数将传递进来的YouTube视频链接转换成简单模式，
     * 即：https://www.youtube.com/watch?v={VIDEO_ID} 这种形式
     * 分别保存至link和videoId属性中
     * @param link
     */
    public void setParseLink(String link) {
        setParseLink(link, "https://www.youtube.com", "/watch?", "v");
    }

    public void setParseLink(String link, String domain, String path, String videoIdKey) {
        if (link.startsWith("http")) {
            // 链接保持从接口获取到的一致。
            this.setLink(link);
            // 链接是一个以【,】分隔的数组，取第一个的链接进行获取视频编号
            String[] links = link.split(",");
            Set<String> videoIdSet = new HashSet<>();
            for (String l: links) {
                String videoId = null;
                if (-1 != l.indexOf("youtu.be")) { // 短链接的YouTube视频地址
                    videoId = l.substring("https://youtu.be/".length());
                } else {
                    videoId = getParams(l).get(videoIdKey);
                }
                if (StringUtils.isBlank(videoId)) { // 如果获取到的VIDEO_ID为空，则不记录，有可能是某个符号错误导致链接解析不到VIDEO_ID
                    continue;
                }
                videoIdSet.add(StringUtils.abbreviate(videoId, "", 11));
            }
            // 由于数据库中最多只能保存下10个VIDEO_ID的值，因此只保留10个好了。
            String videoIds = videoIdSet.stream().limit(10).collect(Collectors.joining(","));
            Assert.hasText(videoIds, "获取到的VIDEO_ID为空：" + link);
            /**
             * 正常的YouTube VIDEO_ID长度应该是11位字符串。
             * 解析出来的VIDEO_ID有可能带有时长信息，因此将后面的时长信息截取掉。
             */
            this.setVideoId(videoIds);
        } else {
            this.setLink(link);
        }
    }

    /**
     * 解析出url参数中的键值对
     * 如 "index.jsp?Action=del&id=123"，解析出Action:del,id:123存入map中
     * @param url url地址
     * @return url请求参数部分
     */
    private static Map<String, String> getParams(String url) {
        Map<String, String> mapRequest = new HashMap<String, String>();

        String[] arrSplit = null;

        String strUrlParam = truncateUrlPage(url);
        if (strUrlParam == null) {
            return mapRequest;
        }
        //每个键值为一组
        arrSplit = strUrlParam.split("[&]");
        for (String strSplit : arrSplit) {
            String[] arrSplitEqual = null;
            arrSplitEqual = strSplit.split("[=]");

            //解析出键值
            if (arrSplitEqual.length > 1) {
                //正确解析
                mapRequest.put(arrSplitEqual[0], arrSplitEqual[1]);

            } else {
                if (arrSplitEqual[0] != "") {
                    //只有参数没有值，不加入
                    mapRequest.put(arrSplitEqual[0], "");
                }
            }
        }
        return mapRequest;
    }

    /**
     * 去掉url中的路径，留下请求参数部分
     * @param strURL url地址
     * @return url请求参数部分
     */
    private static String truncateUrlPage(String strURL) {
        String strAllParam = null;
        String[] arrSplit = null;

        strURL = strURL.trim();

        arrSplit = strURL.split("[?]");
        if (strURL.length() > 1) {
            if (arrSplit.length > 1) {
                if (arrSplit[1] != null) {
                    strAllParam = arrSplit[1];
                }
            }
        }
        return strAllParam;
    }
}